package com.wzdigit.wms.wms.service.core.transfer;

import com.wzdigit.framework.Shift;
import com.wzdigit.wms.basic.client.request.trsn.ScanGoodsSNNewRequest;
import com.wzdigit.wms.basic.client.request.trsn.ScanUpCodeRequest;
import com.wzdigit.wms.basic.client.request.trsn.ScanUpRequest;
import com.wzdigit.wms.basic.client.request.trsn.ScanUpRequest.ScanUpSnItemRequest;
import com.wzdigit.wms.basic.client.response.Result;
import com.wzdigit.wms.basic.client.response.basic.RecommendedLocationResponse;
import com.wzdigit.wms.basic.client.response.basic.WarehouseApiResponse;
import com.wzdigit.wms.basic.domain.dtos.inventory.BindWarehousePositionDto;
import com.wzdigit.wms.basic.domain.dtos.inventory.SnInforDto;
import com.wzdigit.wms.basic.domain.inventory.Goods;
import com.wzdigit.wms.basic.enums.GoodsStatusEnum;
import com.wzdigit.wms.basic.enums.SnScanTypeEnum;
import com.wzdigit.wms.basic.service.code.WhsPermService;
import com.wzdigit.wms.basic.util.HttpSessionUtil;
import com.wzdigit.wms.common.entity.StatusCode;
import com.wzdigit.wms.wms.service.basic.LocationService;
import com.wzdigit.wms.wms.service.basic.WarehouseService;
import com.wzdigit.wms.wms.service.core.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class TransferUpService {

	@Autowired
	private GoodsService goodsService;

	@Autowired
	private LocationService locationService;

	@Autowired
	@Lazy
	private WarehouseService warehouseService;
	
	@Autowired
	private WhsPermService whsPremService;

	/**
	 * 扫描条码，带出信息
	 * @param search
	 * @return
	 */
	public List<SnInforDto> scanGoodsSNNew(ScanGoodsSNNewRequest search) {
		SnScanTypeEnum snScanTypeEnum = SnScanTypeEnum.getEnumByCode(search.getScanType());
		
		// 获取扫描信息
		List<SnInforDto> snInforDtoList = goodsService.selectSnInfosBySn(search.getGoodsSn(), snScanTypeEnum);

		if (snInforDtoList.size() == 0) {
			Shift.fatal("SN[" + search.getGoodsSn() + "]信息不存在!");
		}
		if (snInforDtoList.stream().filter(c -> !c.getStatus().equals(GoodsStatusEnum.WAIT_UP.getCode())
				&& !c.getStatus().equals(GoodsStatusEnum.WAIT_DOWM.getCode())).count() > 0) {
			Shift.fatal(StatusCode.HAS_OTHER_STATUS);
		}
		if(search.getWhsId() != null && !search.getWhsId().equals(snInforDtoList.get(0).getWhsId())) {
			Shift.fatal(StatusCode.NOT_SAME_WHS_ERROR);
		}
		if(search.getSkuCode() != null && search.getPoNo() != null) {
			if(!search.getSkuCode().equals(snInforDtoList.get(0).getSkuCode()) || !search.getPoNo().equals(snInforDtoList.get(0).getPoNo())) {
				Shift.fatal("当前扫描SN与上一个SN订单号或机型不一致，请注意上架情况！");
			}
		}
		
		Goods goods = goodsService.selectBySn(search.getGoodsSn());
		String recommendedLoc = locationService.selectRecommendedUpLocation(goods.getSkuId(), goods.getWhsId(), goods.getPoNo());
		for (SnInforDto snInforDto : snInforDtoList) {
			// 设置推荐库位
			snInforDto.setRecommendedLocation(recommendedLoc);
			// 设置扫描方式
			snInforDto.setTwScanMode(snScanTypeEnum.code);
		}
		return snInforDtoList;
	}
	
	/**
	 * 扫描库位上架
	 * @param dto
	 * @param loginName
	 * @param servletRequest
	 * @return
	 * @throws Exception 
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public Result<?> scanUp(ScanUpRequest dto, HttpServletRequest servletRequest) throws Exception {
		String loginName = HttpSessionUtil.getLoginName(servletRequest);
		
		RecommendedLocationResponse loc = validateWhsPermAndLoc(dto.getLocCode(), servletRequest);
		
		BindWarehousePositionDto input = new BindWarehousePositionDto();
		input.setLocId(loc.getLocId());
		
		// 获取Sn条码集合，根据扫描方式分组
		List<ScanUpSnItemRequest> snList = dto.getSnList();
		Map<Integer, List<ScanUpSnItemRequest>> groupBy = 
				snList.stream().collect(Collectors.groupingBy(ScanUpSnItemRequest::getTwScanMode));
		
		// 单条扫描条码集合
		List<ScanUpSnItemRequest> oneSnList = groupBy.get(SnScanTypeEnum.SELECT_SN.code);
		
		// 整板扫描条码集合
		List<ScanUpSnItemRequest> palletSnList = groupBy.get(SnScanTypeEnum.SELECT_PALLET.code);
		
		if(oneSnList != null && oneSnList.size() > 0) {
			// 调上架SN与库位绑定
			input.setDeletePkg(true);	// 单台扫描需要置空卡板号
			input.setGoodsSns(oneSnList.stream().map(a -> a.getGoodsSn()).distinct().collect(Collectors.toList()));
			goodsService.bindWareHousePosition(input, loginName);
		}
		
		if(palletSnList != null && palletSnList.size() > 0) {
			// 调上架SN与库位绑定
			input.setDeletePkg(false);	// 整板扫描不用置空卡板号
			input.setGoodsSns(palletSnList.stream().map(a -> a.getGoodsSn()).distinct().collect(Collectors.toList()));
			goodsService.bindWareHousePosition(input, loginName);
		}
		return new Result<>(true, "上架成功");
	}
	
	/**
	 * SN库位上架
	 * @param dto
	 * @param loginName
	 * @param servletRequest
	 * @return
	 * @throws Exception 
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public String scanUpCode(ScanUpCodeRequest dto, String loginName, HttpServletRequest servletRequest) throws Exception {
		RecommendedLocationResponse loc = validateWhsPermAndLoc(dto.getLocCode(), servletRequest);
		
		// 调上架SN与库位绑定
		BindWarehousePositionDto input = new BindWarehousePositionDto();
		input.setLocId(loc.getLocId());
		input.setGoodsSns(dto.getSnList());
		input.setDeletePkg(dto.getDeletePkg());
		goodsService.bindWareHousePosition(input, loginName);
		return loc.getLocCode() + "," + loc.getWhsName(); // "库位，仓库名";
	}
	
	/**
	 * 检验用户仓库权限和库位是否关联
	 * @param locCode
	 * @param servletRequest
	 */
	private RecommendedLocationResponse validateWhsPermAndLoc(String locCode, 
			HttpServletRequest servletRequest) {
		// 查询当前用户权限仓库
		List<WarehouseApiResponse> whList = whsPremService.getWarehousePerm(servletRequest);
		// 根据库位编码获取库存+库位信息
		RecommendedLocationResponse loc = locationService.selectWareHouseByLocCode(locCode);
		if (loc == null) {
			Shift.fatal(StatusCode.NOT_EXIST_LOC);
		}
		if (whList.stream().filter(c -> c.getWhsId().equals(loc.getWhsId())).count() == 0) {
			Shift.fatal("当前扫描库位不属于当前登录用户的权限仓库");
		}
		return loc;
	}
}